package com.miyuan.wm.controller;

import com.alibaba.fastjson.JSON;
import com.miyuan.wm.data.UserInfo;
import com.miyuan.wm.enums.ExceptionCodeEnum;
import com.miyuan.wm.exception.BaseException;
import com.miyuan.wm.response.BaseResponse;
import com.miyuan.wm.service.SystemLogService;
import com.miyuan.wm.service.UserService;
import com.miyuan.wm.utils.NetworkUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @ClassName UserController
 * @Description 用户登录登出控制
 */
@RestController
@Api(description = "用户登录登出控制器", tags = {"用户登录登出"})
@Slf4j
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private SystemLogService systemLogService;

    @ApiOperation(value = "登陆接口")
    @GetMapping("/ajaxLogin")
    @ApiImplicitParams({@ApiImplicitParam(name = "userName", value = "账号"),
            @ApiImplicitParam(name = "passWord", value = "密码")})
    public BaseResponse<Boolean> login(@RequestParam(value = "userName") String userName, @RequestParam(value = "passWord") String passWord) {
        boolean flag = false;
        //获得当前用户到登录对象，现在状态为未认证
        Subject subject = SecurityUtils.getSubject();
        //用户名密码令牌
        AuthenticationToken token = new UsernamePasswordToken(userName, passWord);
        Session session = subject.getSession();
        //shiro 使用异常捕捉登录失败消息
        try {
            //将令牌传到shiro提供的login方法验证，需要自定义realm
            subject.login(token);

            flag = true;
        } catch (IncorrectCredentialsException ice) {
            throw new BaseException(ExceptionCodeEnum.USERNAME_OR_PASSWORD_ERROR);
        } catch (UnknownAccountException uae) {
            throw new BaseException(ExceptionCodeEnum.UNKNOWN_ACCOUNT_EXCEPTION);
        } catch (AuthenticationException ae) {
            throw new BaseException(ExceptionCodeEnum.USER_NO_UNAUTHORIZED_ERROR);
        } catch (Exception e) {
            throw new BaseException(ExceptionCodeEnum.LOGIN_ERROR);
        } finally {
            // 当登陆失败则清除session中的用户信息
            if (!flag) {
                session.setAttribute("userInfo", null);
            }
        }

        UserInfo userInfo = (UserInfo) session.getAttribute("userInfo");
        // 记录登入日志
        if (!ObjectUtils.isEmpty(userInfo)) {
            systemLogService.insertAccessRecord(userInfo.getUserID(), userInfo.getUserName(),
                    NetworkUtil.currentIp(), SystemLogService.ACCESS_TYPE_LOGIN);
        }
        return BaseResponse.successOf(subject.isAuthenticated());
    }

    @ApiOperation(value = "退出接口")
    @GetMapping("/logout")
    public BaseResponse<Boolean> logout() {
        //获得当前用户到登录对象
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated()) {
            subject.logout();
        }
        return BaseResponse.successOf(Boolean.TRUE);
    }

    @ApiOperation(value = "修改密码接口")
    @PostMapping("/passwordModify")
    @ApiImplicitParams({@ApiImplicitParam(name = "username", value = "账号"),
            @ApiImplicitParam(name = "oldPassWord", value = "旧密码"), @ApiImplicitParam(name = "newPassWord", value = "新密码"),
            @ApiImplicitParam(name = "repeatPassWord", value = "新密码确认")})
    public BaseResponse<Boolean> passwordModify(@RequestParam String username, @RequestParam String oldPassWord,
                                                @RequestParam String newPassWord, @RequestParam String repeatPassWord) {
        log.info("更新密码请求参数类：[{}, {}, {}, {}]", username, oldPassWord, newPassWord, repeatPassWord);
        UserInfo userInfo = (UserInfo) SecurityUtils.getSubject().getSession().getAttribute("userInfo");
        log.info("当前用户信息：[{}]", JSON.toJSONString(userInfo));
        return userService.updatePassword(userInfo, username, oldPassWord, newPassWord, repeatPassWord);
    }

}
